// i.d(t, { m: () => UserData })

import Data from "../object/Data"
import ObservableMap, { createMap } from "../observer/observable.map"
import UserInfo from "../utils/UserInfo"
import { getUserDisplay } from "../utils/color.util"
import userEnum from "../enum/user.enum"
import modelAccessEnum from "../enum/modelAccess.enum"

export default class UserData extends Data {
  orgAdmin: any
  policies: any[]
  users: ObservableMap<any>
  currentUser: UserInfo
  constructor(e: Partial<UserInfo>, login: boolean, orgAdmin, policies = []) {
    super()
    this.orgAdmin = orgAdmin
    this.policies = policies
    this.name = "users-data"
    this.users = createMap()
    this.currentUser = new UserInfo(
      Object.assign(Object.assign({}, e), {
        modelAccess: e.modelAccess || modelAccessEnum.PUBLIC,
        userStatus: login ? userEnum.KNOWN : userEnum.UNKNOWN
      })
    )
    this.addUser(this.currentUser)
  }
  loadSearchResults(e, t, i) {
    this.atomic(() => {
      e.forEach(e => {
        this.loadUser(Object.assign(Object.assign({}, e), { userStatus: userEnum.KNOWN }))
      }),
        t.forEach(e => {
          this.users.get(e) || this.loadUser({ email: e, id: "", userStatus: i })
        })
    })
  }
  loadKnownUsers(e) {
    this.atomic(() => {
      e.forEach(e => {
        this.loadKnownUser(e)
      })
    })
  }
  loadKnownUser(e: Partial<UserInfo>) {
    return this.loadUser(Object.assign(Object.assign({}, e), { userStatus: userEnum.KNOWN }))
  }
  loadContributor(e) {
    const t = this.users.get(e.email)
    return (
      t ||
      this.loadUser(
        Object.assign(Object.assign({}, e), {
          userStatus: userEnum.CONTRIBUTOR
        })
      )
    )
  }
  loadFailedUser(e) {
    return this.loadUser(Object.assign(Object.assign({}, e), { userStatus: userEnum.FAILED }))
  }
  loadUser(e: Partial<UserInfo>) {
    let t = this.users.get(e.email)
    e.email === this.currentUser.email ||
      (t && t.userStatus === userEnum.KNOWN && t.modelAccess !== modelAccessEnum.PUBLIC) ||
      ((t = new UserInfo(e)), t ? this.users.set(e.email || "0", t) : this.addUser(t))
    return t
  }
  getUserInfoByEmail(e) {
    return this.users.has(e) ? this.users.get(e) : null
  }
  getUserInfoById(e) {
    return "" === e ? null : this.users.values.find(t => t.id === e) || null
  }
  getUserDisplay(e) {
    return this.users.has(e) ? this.users.get(e) : getUserDisplay(e)
  }
  iterate(e) {
    for (const t of this.users) e(t)
  }
  getUsersWhoMayNeedAccess() {
    const e = {}
    return (
      this.users.values.forEach(t => {
        ;(t.userStatus === userEnum.KNOWN && t.modelAccess !== modelAccessEnum.PUBLIC) || (e[t.email] = t)
      }),
      e
    )
  }
  getKnownUsers() {
    return this.users.values.filter(e => e.userStatus === userEnum.KNOWN)
  }
  addUser(e) {
    this.users.has(e.email) || this.users.set(e.email, e)
  }
  getCurrentUser() {
    return this.currentUser
  }
  isLoggedIn() {
    return !!this.currentUser.id
  }
  isPolicyFlagEnabled(e) {
    return this.policies.includes(e)
  }
  isOrgAdmin() {
    return this.orgAdmin
  }
  isInviter() {
    return this.orgAdmin
  }
  isEditor() {
    return this.currentUser.modelAccess === modelAccessEnum.FULL
  }
  isCommenter() {
    const { modelAccess: e } = this.currentUser
    return e === modelAccessEnum.VIEWER || e === modelAccessEnum.FULL
  }
  getCurrentUserId() {
    return this.currentUser.id
  }
  onUsersChanged(e) {
    return this.users.onChanged(e)
  }
}
